// FUNCTION_CALL_CLOBBER
// * Registers that are presumed to be destroyed (volatile) across a function call
// From System V ABI specification for the i386. See:
//     http://www.caldera.com/developers/devspecs/abi386-4.pdf 
//     System V Application Binary Interface, Intel386 Architecture Processor Supplement, Fourth Edition
//     PDF pages 37-38 (pages 3-11 and 3-12)
#define FUNCTION_CALL_CLOBBER "%eax", "%ecx", "%edx", /* EFLAGS, */ "%memory"

#define ISA_EXT_0_ARG(SPR, /*Clobber*/...) \
__ASM__ __VOLATILE__ (       \
    "movl %0, %%eax\n"       \
    "int $0x0\n"             \
    : /* no outputs */       \
    : "i" (SPR)              \
    : "%eax", ## __VA_ARGS__ \
    );

#define ISA_EXT_1_ARG(SPR, Arg1, /*Clobber*/...) \
__ASM__ __VOLATILE__ (                     \
    "movl %0, %%eax\n"                     \
    "movl %1, %%ecx\n"                     \
    "int $0x0\n"                           \
    : /* no outputs */                     \
    : "i" (SPR), "mibdDS" (Arg1)    \
    : "%eax", "%ecx", ## __VA_ARGS__       \
    );

#define ISA_EXT_2_ARG(SPR, Arg1, Arg2, /*Clobber*/...) \
__ASM__ __VOLATILE__ (                                          \
    "movl %0, %%eax\n"                                          \
    "movl %1, %%ecx\n"                                          \
    "movl %2, %%edx\n"                                          \
    "int $0x0\n"                                                \
    : /* no outputs */                                          \
    : "i" (SPR), "mibdDS" (Arg1), "mibdDS" (Arg2) \
    : "%eax", "%ecx", "%edx", ## __VA_ARGS__ \
    );

#define ISA_EXT_0_ARG_RET(SPR, Dest) \
__ASM__ __VOLATILE__ (        \
    "movl %1, %%eax\n"        \
    "int $0x0\n"              \
    "movl %%eax, %0\n"        \
    : "=g" (Dest)             \
    : "i" (SPR)               \
    : "%eax"                  \
    );

#define ISA_EXT_1_ARG_RET(SPR, Dest, Arg1, /*CLOBBER*/...) \
__ASM__ __VOLATILE__ (                  \
    "movl %1, %%eax\n"                  \
    "movl %2, %%ecx\n"                  \
    "int $0x0\n"                        \
    "movl %%eax, %0\n"                  \
    : "=g" (Dest)                       \
    : "i" (SPR), "mibdDS" (Arg1) \
    : "%eax", "%ecx", ## __VA_ARGS__ \
    );

#define ISA_EXT_2_ARG_RET(SPR, Dest, Arg1, Arg2, /*Clobber*/...) \
__ASM__ __VOLATILE__ (                                          \
    "movl %1, %%eax\n"                                          \
    "movl %2, %%ecx\n"                                          \
    "movl %3, %%edx\n"                                          \
    "int $0x0\n"                                                \
    "movl %%eax, %0\n"                                          \
    : "=g" (Dest)                                               \
    : "i" (SPR), "mibdDS" (Arg1), "mibdDS" (Arg2) \
    : "%eax", "%ecx", "%edx", ## __VA_ARGS__   \
    );
